<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2022/4/6
 * Time: 13:50
 */

namespace app\api\controller;
use app\admin\model\ServiceHall;
use app\common\controller\Api;
use think\Db;
use addons\epay\library\QRCode;
use addons\epay\library\Service;

use pay\wxpay\Wxpay;
class Play extends Api
{
    protected $noNeedLogin = ['wxNotify','notifyx','qrcode'];
    protected $noNeedRight = '*';

    /**
     * 微信支付(公众号支付&PC扫码支付)
     * @return string
     */
    public function wechat($order_id)
    {
        $userInfo = $this->auth->getUserinfo();

        $config = Service::getConfig('wechat');

//        $type = $this->request->request('type');
        $method = $this->request->request('pay_type', 'miniapp');
        $type = 'wechat';

        if(!$order_id)
            $this->error('缺少参数');
        $orderInfo = Db::name('order')->where('id',$order_id)->find();
        if(!$orderInfo)
            $this->error('无此订单');
        $amount = $orderInfo['price'];
        $this->request->filter('trim');
        $out_trade_no = $orderInfo['order_on'];
        $title = $orderInfo['title'];

        if (!$amount || $amount < 0) {
            $this->error("支付金额必须大于0");
        }

        if (!$type || !in_array($type, ['alipay', 'wechat'])) {
            $this->error("支付类型错误");
        }

        $params = [
            'type'         => $type,
            'orderid' => $out_trade_no,
            'title'        => $title,
            'amount'       => $amount,
            'method'       => $method,
            'openid'       => $userInfo['openid'],
            //'auth_code'    => $auth_code,
            'notifyurl'    => $config['notify_url'],
            'returnurl'    => '',
        ];

        $response = Service::submitOrder($params);
        if($method=='miniapp')
        {
            $this->success('',$response);
        }
        else
        {
            if($response['return_code']=='SUCCESS')
            {
                $url2 = $this->qrcode($response["code_url"]);
                $this->success('',['code'=>$url2]);
            }
            $this->error($response['return_msg']);
        }

    }

    public function doPay($order_id)
    {

        $userInfo = $this->auth->getUserinfo();

        $config = Service::getConfig('wechat');
        if(!$order_id)
            $this->error('缺少参数');
        $orderInfo = Db::name('order')->where('id',$order_id)->find();
        if(!$orderInfo)
            $this->error('无此订单');
        $wxpay = new Wxpay();
        $title = $orderInfo['title'];
        $amount = $orderInfo['price'];
        if (!$amount || $amount < 0) {
            $this->error("支付金额必须大于0");
        }

        $body = [
            'openid'   => $userInfo['openid'],
            'body'     => $title,//标题
            'attach'   => $title,// 描述
            'trade_no' => $orderInfo['order_on'],//订单号
            'money'    => ceil($amount*100),//价格
            'tag'=>'w',
            'notify_url' => $config['notify_url'],//no
        ];
        //dump($body);die;
        $mydata = $wxpay->index($body);
        $mydata = json_decode($mydata,true);

        $this->success('',$mydata);
    }
    
    public function doPay1()
    {

       
        $config = Service::getConfig('wechat');
       
        $wxpay = new Wxpay();
        $title = 'ceshi';
        $amount = 0.01;
        if (!$amount || $amount < 0) {
            $this->error("支付金额必须大于0");
        }
        $out_trade_no = date("YmdHis") . mt_rand(100000, 999999);
        $body = [
            'openid'   => 'o0ubV4td4XtofT377IwT5_rfzgu8',
            'body'     => $title,//标题
            'attach'   => $title,// 描述
            'trade_no' => $out_trade_no,//订单号
            'money'    => ceil($amount*100),//价格
            'tag'=>'w',
            'notify_url' => $config['notify_url'],//no
        ];
        //dump($body);die;
        $mydata = $wxpay->index($body);
        $mydata = json_decode($mydata,true);
        print_r($mydata);exit;
        $this->success('',$mydata);
    }

    //创建订单
    public function createOrder()
    {
        if(!$id = input('post.id'))
            $this->error('缺少参数');

        if(!$type = input('post.type'))
            $this->error('缺少参数');
        if(!$state = input('post.state'))
            $this->error('缺少参数');
        if(!$name = input('post.name'))
            $this->error('姓名不能为空');
        if(!$id_card = input('post.id_card'))
            $this->error('身份证不能为空');
        $preg_card='/(^\d{15}$)|(^\d{17})([0-9]|X)$/isu';
        if(!preg_match($preg_card,$id_card)){
            $this->error('身份证格式不正确');
        }

        if(!$mobile = input('post.mobile'))
            $this->error('手机号不能为空');
        $preg_phone='/^1[345789]\d{9}$/ims';
        if(!preg_match($preg_phone,$mobile)){
            $this->error('手机号格式不正确');
        }
        if(!in_array($type,[1,2,3]))
            $this->error('type参数类型错误');

        if($type==3)
        {
            $info = Db::name('rm_programme')->where('id',$id)->find();
        }
        else
        {
            $info = Db::name('programme')->where('id',$id)->find();
        }
        if(!$info)
            $this->error('无此商品');
        $time = time();
        $out_trade_no = date("YmdHis").$this->auth->id. mt_rand(100000, 999999);
        $data = [];
        $data['user_id'] = $this->auth->id;
        $data['order_on'] = $out_trade_no;
        $data['image'] = $info['image'];
        $data['type'] = $type;
        $data['state'] = $state;
        if($type==1)
        {
            $data['price'] = $info['paid_view'];
        }
        else if($type==2)
        {
            $data['price'] = $info['                                                                                       '];
        }
        else
        {
            $data['price'] = $info['price'];
        }
        $data['title'] = $info['title'];
        $data['programme_id'] = $id;
        $data['createtime'] = $time;
        $data['updatetime'] = $time;

        $signArr = [];
        $signArr['rm_programme_id'] = $id;
        $signArr['name'] = $name;
        $signArr['id_card'] = $id_card;
        $signArr['mobile'] = $mobile;
        $signArr['rm_programme_id'] = $id;
        $signArr['order_on'] = $out_trade_no;
        $signArr['createtime'] = $time;
        $signArr['updatetime'] = $time;
        $signArr['user_id'] = $this->auth->id;
        $res = 0;
        Db::startTrans();
        try{
            $res = Db::name('order')->insertGetId($data);
            if($state==2)
            {
                Db::name('sign_up')->insert($signArr);
            }

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();

            $this->error('订单创建失败');
        }

        $this->wechat($res);
        //$this->doPay($res);
        //$this->success('订单创建成功',['order_id'=>$res]);

    }


    /**
     * 支付成功回调
     */
    public function notifyx()
    {
        $type = $this->request->param('type');
        if($type=='wechat')
        {
            $this->wxNotify();
        }

        echo "success";
        return;
    }

    //微信支付回调

    /**
     * @return bool
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function wxNotify()
    {

//        $xml = file_get_contents('php://input');//监听是否有数据传入
//        if($xml!=''){//如果有数据传入，则将传入的数据写入到xml.txt文件
//            $fp = fopen('xml'.mt_rand(100000, 999999).'.txt','w');
//            fwrite($fp,$xml);
//            fclose($fp);
//        }
        require_once EXTEND_PATH."wx_sdk/example/log.php";
        //获取返回的xml
        $testxml = file_get_contents("php://input");
        //将xml转化为json格式
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        //转成数组
        $result = json_decode($jsonxml, true);

        if ($result) {

            //如果成功返回了
            if(!is_dir(ROOT_PATH."/public/logs/"))
            {
                mkdir(iconv("UTF-8", "GBK", ROOT_PATH."/public/logs/"),0777,true);
            }
            $logHandler= new \CLogFileHandler(ROOT_PATH."/public/logs/".date('Y-m-d').'.log');
            \Log::Init($logHandler, 15);
            \Log::INFO(json_encode(['time'=>date("Y-m-d H:i:s",time()),'data'=>$result,'ip' =>  request()->ip()],JSON_UNESCAPED_UNICODE));

            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
                //进行改变订单状态等操作。。。。 ['return_msg'=>['transaction_id','out_trade_no','attach','total_fee']]
                //TODO: 1.检查订单的支付状态，如果以付款则，直接返回xml数据，或者直接返回false|true
                $_where = ['order_on' => $result['out_trade_no']];
                $order = Db::name('order')->where($_where)->find();

                if ($order['status']==1) {
                    //写入日志-$result['out_trade_no']

                    \Log::ERROR(json_encode(['wxNotify-TODO-1' => '订单号：' . $result['out_trade_no']
                        . "不存在或已经付款", 'ip' =>  request()->ip()],JSON_UNESCAPED_UNICODE));
                    return false;
                }

                //TODO: 2校验签名--保障数据是来源微信的服务器；
                //TODO: 2.1:校验参数----查看return_msg中是否有我们发送给微信服务器端的数据attach[商家数据包]
                if (isset($result['attach']) && $result['attach'] != "wwwahai574com") {
                    //写入日志-attach数据包错误
                    \Log::WARN(json_encode(['wxNotify-TODO-2.1' => "attach数据包错误", 'ip' =>  request()->ip()]));
                    return false;
                }

                //TODO: 2.2:验证签名
                //获取返回的所以参数
                //这里是要把微信返给我们的所有值，先删除sign的值，其他值 按ASCII从小到大排序；
                $xmlSign = "我是默认的sign,如果没有获取到微信返回的sign值，那么就写入日志";
                foreach ($result as $k => $v) {
                    if ($k == 'sign') {
                        $xmlSign = $result[$k];
                        unset($result[$k]);
                    };
                }

                //排序
                ksort($result);
                $sign = http_build_query($result);
                //md5处理
                //vendor("wxpay.WxPay#Config");
                //$config = new \WxPayConfig();
                $config = Service::getConfig('wechat');

                $string = $sign . '&key=' . $config['key'];
                //加密的方式：下面2选1 Wxpay.Config.php中的配置是HMAC-SHA256,所以不用md5加密
                //如果是“MD5”,则：$sign = md5($string);
                $sign = md5($string);
                //$sign = hash_hmac("sha256",$string ,$config['key']);
                //转大写
                $sign = strtoupper($sign);
                //\Log::INFO(json_encode(['string'=>$string,'sign'=>$sign],JSON_UNESCAPED_UNICODE));
                //验签名。默认支持MD5
                //验证加密后的32位值和 微信返回的sign 是否一致！！！

                if ($sign === $xmlSign) {
                    //TODO: 3修改订单为付款状态
                    \Log::INFO(json_encode(['wxNotify-TODO-3'=>'验证签名正确，开始更新订单的状态','string'=>$string,'sign'=>$sign],JSON_UNESCAPED_UNICODE));
                    //更新订单状态，本来应该给微信返回值说明支付成功的，不返回值，微信就只会触发多次请求，
                    //反正查询条件必须是未支付的订单才会改状态，所以多次请求，只有第一次真正成功才会写入数据库
                    $data['status'] = 1;
                    $data['completetime'] = date("Y-m-d H:i:s", time());
                    $data['order_business'] =$result['transaction_id'];

                    if($order['type']==3 && $order['state']==2)
                    {
                        Db::name('sign_up')->where(['order_on'=>$result['out_trade_no']])->update(['status'=>1]);
                    }

                    Db::name('order')->where(['order_on'=>$result['out_trade_no']])->update($data);
                    if($order['price']>=1)
                    {
                        \app\common\model\User::score(floor($order['price']),$order['user_id'],'购买'.$order['title'].'赠送积分');
                    }
                    //\Log::INFO(json_encode(['wxNotify-tody-3'=>'验证签名正确，结束更新订单的状态'],JSON_UNESCAPED_UNICODE));
                }else{
                    \Log::ERROR(json_encode(['wxNotify-TODO-3' => "签名错误",'xml中的sign'=>$xmlSign,'xml组成的sign'=>$sign, '访问者ip' =>  request()->ip()],JSON_UNESCAPED_UNICODE));
                }

            }
        }
    }

    /**
     * 生成二维码
     */
    public function qrcode($url)
    {
        $text = $url;

        //如果有安装二维码插件，则调用插件的生成方法
        if (class_exists("\addons\qrcode\library\Service") && get_addon_info('qrcode')['state']) {

            $qrCode = \addons\qrcode\library\Service::qrcode(['text' => $text]);
            return $qrCode->writeDataUri();
            /*$response = Response::create()->header("Content-Type", "image/png");

            header('Content-Type: ' . $qrCode->getContentType());
            $response->content($qrCode->writeString());*/
            //return $response;
        } else {

            $qr = QRCode::getMinimumQRCode($text);
            return $im = $qr->createImage(8, 5);

            header("Content-type: image/png");
            imagepng($im);
            imagedestroy($im);
            return;
        }
    }
}